/**
 * Copyright (c) 2008, Noel Lynch All rights reserved. Redistribution and use
 * in source and binary forms, with or without modification, are permitted
 * provided that the following conditions are met: Redistributions of source
 * code must retain the above copyright notice, this list of conditions and the
 * following disclaimer. Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution. Neither
 * the name of Noel Lynch nor the names of contributors may be used to
 * endorse or promote products derived from this software without specific prior
 * written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.sceneworker;

import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.lang.reflect.Constructor;
import java.util.Hashtable;

import javax.swing.JDialog;
import javax.swing.JTree;
import javax.swing.JViewport;

import com.acarter.composabletree.ComposableTreeModel;
import com.acarter.jmejtree.JMEJTreePopUp;
import com.acarter.scenemonitor.SceneMonitor;
import com.acarter.scenemonitor.dialog.MonitorDialog;
import com.jme.scene.Spatial;
import com.sceneworker.app.ISceneWorkerToolsController;
import com.sceneworker.app.StandardJMEController;
import com.sceneworker.monitorpopup.SceneWorkerPopUp;


/**
 * Scene Worker
 * @author noellynch
 *
 */
public class SceneWorker {

	private		SceneMonitorExtensions					mcl_extensions;
	private		ISceneWorkerToolsController				mcl_handler;
	private		boolean									mb_toolsEnabled;
	private		float									mf_lastTimePerFrame;
	
	
	static		private		SceneWorker		mcl_this;
	
	static	public	SceneWorker		inst() {
		if(mcl_this == null) {
			mcl_this = new SceneWorker();
		}
		
		return mcl_this;
	}
	
	public	boolean		areToolsEnabled() {
		return mb_toolsEnabled;
	}
	
	public	void	setToolsEnabled(boolean b_toolsEnabled) {
		mb_toolsEnabled = b_toolsEnabled;
	}
	
	public	SceneWorker() {
		mcl_extensions = new SceneMonitorExtensions();
	}
	
	public	void	initialiseSceneWorkerTools(Object cl_obj) {
		if(cl_obj instanceof Spatial) {
			Spatial		lcl_n = (Spatial)cl_obj;
			mcl_handler = new StandardJMEController();
			mcl_handler.initialise(lcl_n);
			System.out.println("tools initialised...");
		}
		
	}
	
	public	void	update(float f_timePerFrame) {
		mf_lastTimePerFrame = f_timePerFrame;
		if(mcl_handler != null) {
			mcl_handler.update(f_timePerFrame);
		} else {
			SceneMonitor.getMonitor().updateViewer(f_timePerFrame);
		}
	}
	
	public	void	render() {
		if(mcl_handler != null) {
			mcl_handler.render(mf_lastTimePerFrame);
		}
	}
	
	public	void	addTreeRepresentationBinding(Class<?> cl_objectClass, Class<? extends ComposableTreeModel> cl_treeRepClass) {
		SceneWorkerAppMonitorDialog.addTreeRepresentationBinding(cl_objectClass, cl_treeRepClass);
	}
	
	public	void	initialiseSceneWorkerAndMonitor() {
		SceneMonitor.monitorDialogClassName = SceneWorkerAppMonitorDialog.class.getName();
		SceneMonitor.getMonitor().showViewer(true);
		
		SceneWorkerPopupListener popup = new SceneWorkerPopupListener(SceneWorkerPopUp.class);
		SceneMonitor.getMonitor().getMonitorTree().addMouseListener(popup);
		
		buildAllExtenstions();
	}
	
	public	void	deactivate() {
		SceneMonitor.getMonitor().showViewer(false);
		((MonitorDialog)SceneMonitor.getMonitor().getMonitorDialog()).unregisterAllNodes();
	}
	
	public	void	unload() {
		SceneMonitor.getMonitor().cleanup();
	}
	
	public	void	buildAllExtenstions() {
		mcl_extensions.buildTextExtension();
		mcl_extensions.buildTextureStateExtension();
		mcl_extensions.buildTriMeshExtension();
		mcl_extensions.buildBoxExtension();
		mcl_extensions.buildQuadExtension();
		mcl_extensions.buildSpatialTransformerExtension();
		mcl_extensions.buildArrowExtension();
		mcl_extensions.buildCylinderExtension();
		mcl_extensions.buildPassNodeExtenstions();
		mcl_extensions.buildPassNodeStateExtenstions();
		mcl_extensions.buildFragmentProgramStateExtenstions();
		mcl_extensions.buildVertexProgramStateExtenstions();
		mcl_extensions.buildGLSLShaderObjectsStateExtenstions();
		mcl_extensions.buildBeanShellControllerExtenstions();
		mcl_extensions.buildDiscreteLODNodeExtension();
		mcl_extensions.buildClodMeshExtension();
		mcl_extensions.buildAreaClodMeshExtension();
		mcl_extensions.buildSphereExtension();
		mcl_extensions.buildCapsuleExtension();
		mcl_extensions.buildDiskExtension();
		mcl_extensions.buildDomeExtension();
		mcl_extensions.buildPQTorusExtension();
		mcl_extensions.buildPyramidExtension();
		mcl_extensions.buildRoundedBoxExtension();
		mcl_extensions.buildTorusExtension();
		mcl_extensions.buildTubeExtension();
		mcl_extensions.buildMeshAnimationControllerExtension();
		mcl_extensions.buildPassExtension();
		mcl_extensions.buildPassManagerExtension();
	}
		
	/**
	 * Mouse listener used to activate popup menus.
	 * 
	 * @author Carter
	 */
	public class SceneWorkerPopupListener extends MouseAdapter {
		
		private Class<?> mcl_popUpMenuClass;
		
		public SceneWorkerPopupListener(Class<?> cl_c) {
			
			mcl_popUpMenuClass = cl_c;
		}

		public void mousePressed(MouseEvent e) {
			
			if(e.isPopupTrigger())
				doPopUp(e);
		}

		public void mouseReleased(MouseEvent e) {
			
			if(e.isPopupTrigger())
				doPopUp(e);
		}

		private void doPopUp(MouseEvent cl_e) {

			try {
				Constructor<?> lcl_ctor = mcl_popUpMenuClass.getDeclaredConstructor(JDialog.class);
				lcl_ctor.setAccessible(true);
				
				JDialog dialog = SceneMonitor.getMonitor().getMonitorDialog();
				
				JMEJTreePopUp lcl_popUp = (JMEJTreePopUp) lcl_ctor.newInstance(dialog);
				
				JTree		lcl_tree = (JTree)cl_e.getSource();
				JViewport	lcl_view = (JViewport)lcl_tree.getParent();
				Rectangle	lcl_viewRect = lcl_view.getViewRect();
				lcl_popUp.show(dialog, cl_e.getX(), cl_e.getY() - lcl_viewRect.y);
			}
			catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	
}
